package nirvana.core.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import nirvana.core.security.SecurityCredential;

import java.sql.Timestamp;
import java.util.Date;
import java.util.List;


/**
 * @author Joseph.Li
 * @author joseph.li@king-v.com
 * Created in 2022-07-08 16:46
 */
@Slf4j
public class JwtTools {

    /**
     * todo: 修改为配置
     */
    private static final String SUBJECT = "green-mall";


    /**
     * todo: 修改为配置
     */
    private static final String SECRET = "GREENMALLTokenSecretKr1234";


    /**
     * 根据用户信息获取token
     *
     * @param credential
     * @param expiration
     * @return
     */
    public static String generateToken(SecurityCredential credential, int expiration) {
        if (credential == null || credential.getId() == null || credential.getUsername() == null) {
            return null;
        }
        String token = Jwts.builder().setSubject(SUBJECT)
                .claim("id", credential.getId())
                .claim("username", credential.getUsername())
                .claim("roleIds", credential.getRoleIds())
                .claim("tenantId", credential.getTenantId())
                .claim("isSystemTenant", credential.getIsSystemTenant())
                .claim("userType", credential.getUserType())
                .claim("isRefresh", credential.getIsRefresh())
                .claim("loginTime", credential.getLoginTime())
                .setIssuedAt(new Date())
                .setExpiration(generateExpirationDate(expiration))
                .signWith(SignatureAlgorithm.HS256, SECRET)
                .compact();
        return token;
    }


    /**
     * 生成token的过期时间
     *
     * @param expiration 过期时间  单位min
     * @return 返回过期得时间
     */
    private static Date generateExpirationDate(int expiration) {
        return new Date(System.currentTimeMillis() + expiration * 1000L * 60);
    }

    /**
     * 从token中获取JWT中的负载
     *
     * @param token token值
     * @return claims
     */
    private static Claims getClaimsFromToken(String token) {
        Claims claims = null;
        try {
            claims = Jwts.parser()
                    .setSigningKey(SECRET)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            log.info("JWT格式验证失败:{}", token);
        }
        return claims;
    }


    /**
     * 从token中获取登录用户名
     *
     * @param token
     * @return
     */
    public static SecurityCredential getUserInfoFromToken(String token) {
        SecurityCredential securityCredential = null;
        try {
            Claims claims = getClaimsFromToken(token);
            Long id = claims.get("id", Long.class);
            String name = claims.get("username", String.class);
            List<Long> roleIds = claims.get("roleIds", List.class);
            Long tenantId = claims.get("tenantId", Long.class);
            Boolean isSystemTenant = claims.get("isSystemTenant", Boolean.class);
            Integer userType = claims.get("userType", Integer.class);
            Boolean isRefresh = claims.get("isRefresh", Boolean.class);
            Long loginTimeLong = claims.get("loginTime", Long.class);
            Timestamp  loginTime=new Timestamp(loginTimeLong);
            securityCredential = new SecurityCredential(id, name, roleIds, tenantId, isSystemTenant, userType, isRefresh, loginTime);
        } catch (Exception ignored) {

        }
        return securityCredential;
    }


    /**
     * 判断token是否已经失效
     *
     * @param token token字符串
     * @return 返回是否失效
     */
    public static boolean isTokenExpired(String token) {
        Date expiredDate = getExpiredDateFromToken(token);
        return expiredDate.before(new Date());
    }


    /**
     * 从token中获取过期时间
     *
     * @param token
     * @return
     */
    public static Date getExpiredDateFromToken(String token) {
        Claims claims = getClaimsFromToken(token);
        return claims.getExpiration();
    }


}
